//================================================
//
//                       _oo0oo_
//                      o8888888o
//                      88" . "88
//                      (| -_- |)
//                      0\  =  /0
//                    ___/`---'\___
//                  .' \\|     |// '.
//                 / \\|||  :  |||// \
//                / _||||| -:- |||||- \
//               |   | \\\  -  /// |   |
//               | \_|  ''\---/''  |_/ |
//               \  .-\__  '-'  ___/-. /
//             ___'. .'  /--.--\  `. .'___
//          ."" '<  `.___\_<|>_/___.' >' "".
//         | | :  `- \`.;`\ _ /`;.`/ - ` : | |
//         \  \ `_.   \_ __\ /__ _/   .-` /  /
//     =====`-.____`.___ \_____/___.-`___.-'=====
//                       `=---='
//
//
//     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
//               佛祖保佑         永无BUG
//
//
//
//================================================
//
// Created by Huiyi on 2021/4/20.
//
//@模块名称 扩展功能支持库
//@依赖   module_base.h
//@版本   1.1
//@日期   2020-04-20
//@作者   Huiyi
//@模块备注 封装多种常用功能
//项目gitee地址 https://gitee.com/LoveA/XC_Extensions.git
//引用库:
//cpp-httplib
//MD5
//OSPLATFORMUTIL
//sole

#pragma once
#ifndef XL_XExpand_H
//@隐藏{
#define XL_XExpand_H    //防止复用
//#define CPPHTTPLIB_OPENSSL_SUPPORT  //网页类开启ssl
//==
//#include <winreg.h>
#include <cstdarg>
#include <objbase.h>
#pragma comment (lib,"Ole32.lib")
#pragma comment (lib,"Advapi32.lib")
#pragma comment (lib,"version.lib")
#include "httplib.h"
#include "osplatformutil.h"
#include "MD5.h"
#include "base64/base64.h"
#include "sole/sole.hpp"



//cmd回显函数
typedef bool (*X_System_RunCmd_res) (const char* cmd);

//#include "D:\app\XCIDE\data\VC\XC-Module\1_核心模块\1_基础模块\module_base.h"
//@隐藏}


//@src  "MD5.cpp"
//@src  "string.cpp"
//@src  "coding.cpp"
//@src  "check.cpp"
//@src  "array.cpp"
//@src  "system.cpp"
//@src  "network.cpp"
//@src  "base64/base64.cpp"
//@src  "SystemClassReg.cpp"
//@src  "program.cpp"
//@src  "file.cpp"
//@src  "form.cpp"
//@src  "thread.cpp"

//@隐藏{
//@/lib "libcrypto.lib"
//@/lib "libssl.lib"
//@隐藏}

//@lib "Advapi32.lib"

// TODO: 文本操作
//@分组{  文本操作



//@参数   随机长度
//@别名   文本_取随机文本A (长度)
CXTextA X_String_GetRandStrA (int len);

//@参数   字符串
//@别名   文本_到小写A (文本)
CXTextA X_String_ToLowerA(const char* str);

//@参数   字符串
//@别名   文本_到大写A (文本)
CXTextA X_String_ToUpperA(const char* str);

//@别名   文本_取中间文本A(源文本,前文本,后文本,起始位置,不区分大小写)
CXTextA X_String_GetMiddleTextA(const char* text,const char*frontstr,const char*backstr,int begin=0,bool ifnotcasesensitive=false);

//@别名   文本_删首尾空A(文本)
CXTextA X_String_TrimA(CXTextA str);

//@别名   文本_子文本替换A (源字符串,被替换字符串,用作替换的字符串,起始位置,最大替换次数)
CXTextA X_String_SubreplaceA(string resource_str, string sub_str, string new_str="",int begin=0,int MaxRep=-1);

//@别名   文本_倒找文本A(源字符串,被寻找字符串,起始位置)
int X_String_RfindA(const char*source ,const char* match,int index=-1);

//@别名   文本_取左边A ()
CXTextA X_String_GetLeftA(const char*text,int num);

//@别名   文本_取右边A ()
CXTextA X_String_GetRightA(const char*text,int num);

//@别名   文本_分割文本A (文本,分割字符,返回数组)
int X_String_SplitWithStlA(CXTextA str, CXTextA pattern, CXVector<CXTextA>&rets);



//@分组}  文本操作
// TODO: 算术运算
//@分组{  算术运算


//@备注   将指定数值每一个比特位的值取反后返回
//@别名   运算_位取反(数值)
int X_Math_Bnot(int num);

//@别名   运算_左移(欲移动的整数,欲移动的位数)
int X_Math_Shl(int num,int Bit);

//@别名   运算_右移(欲移动的整数,欲移动的位数)
int X_Math_Shr(int num,int Bit);

//@隐藏{
//
#define X_Math_MakeLong(a, b) ((LONG)(((WORD)(a)) | ((DWORD)((WORD)(b))) << 16))

#define X_Math_MakeWord(a,b) ((WORD) (((BYTE) (a)) | ((WORD) ((BYTE) (b))) << 8))
//位与重载模板
template <typename T>
int X_Math_Dand(const T& t){return t;};
template <typename T, typename ... Args>
int X_Math_Dand(const T& head, const Args... args){return head & X_Math_Dand<int>(args...);};

//位或重载模板
template <typename T>
int X_Math_Bor(const T& t){return t;};
template <typename T, typename ... Args>
int X_Math_Bor(const T& head, const Args... args){return head | X_Math_Bor<int>(args...);};

//位异或重载模板
template <typename T>
int X_Math_Bxor(const T& t){return t;};
template <typename T, typename ... Args>
int X_Math_Bxor(const T& head, const Args... args){return head ^ X_Math_Bxor<int>(args...);};

//@隐藏}

/*@声明
//@别名 运算_位或()
int X_Math_Bor (...);

//@别名 运算_位异或()
int X_Math_Dxor (...);

//@别名 运算_位与()
int X_Math_Dand (...);

//@备注 将第一个整数的低16位放置到结果整数的低16位，将第二个整数的低16位放置到结果整数的高16位，以此合并成一个整数，并返回合并后的结果。
//@别名 运算_合并整数()
int X_Math_MakeLong(int num1,int num2);

//@备注 将第一个整数的低8位放置到结果短整数的低8位，将第二个整数的低8位放置到结果短整数的高8位，以此合并成一个短整数，并返回合并后的结果。
//@别名 运算_合并短整数()
int X_Math_MakeWord (int num1,int num2);

*/


//@分组}  算术运算
// TODO: 编码字节
//@分组{  编码字节



//@参数   宽文本字节指针
//@参数   代码页 [可空]
//@别名   编码_WToA(宽文本字节,代码页)
CXTextA X_Coding_WToA(const wchar_t* wp, size_t m_encode=CP_ACP);

//@参数   文本指针
//@参数   代码页
//@别名   编码_AToW(文本字节,代码页)
CXText X_Coding_AToW(const char* c, size_t m_encode = CP_ACP);

//@参数   文本指针
//@别名   编码_Utf8转Gbk(utf8文本)
CXTextA X_Coding_Utf82Gbk(const char* utf8);

//@参数   文本指针
//@别名   编码_Unicode转Utf8(Unicode)
CXTextA X_Coding_UnicodeToUtf8(const wchar_t* unicode);

//@参数   文本指针
//@别名   编码_GBK转Utf8(文本)
CXTextA X_Coding_GBKToUtf8(const char* str);



//@分组}  编码字节
// TODO: 加密解密
//@分组{  加密解密



//@别名   校验_取MD5_Ascii(文本)
CXTextA X_Check_GetMD5_Ascii (const char* str);

//@别名   校验_取MD5_Unicode(文本)
CXTextA X_Check_GetMD5_Unicode (CXText data);

//@别名   校验_取MD5_字节集(字节集)
CXTextA X_Check_GetMD5_Bytes (CXBytes data);

//@别名   校验_Base64_编码 (文本)
CXTextA X_Check_BASE64_EnCode (CXTextA data);

//@别名   校验_Base64_解码 (文本)
CXTextA X_Check_GetMD5_DeCode (CXTextA data);

//@别名   校验_Base64_编码_字节集 (字节集)
CXTextA X_Check_BASE64_EnCode_Bytes (CXBytes data);

//@别名   校验_Base64_解码_字节集 (字节集)
CXTextA X_Check_GetMD5_DeCode_Bytes (CXBytes data);



//@分组}  加密解密
// TODO: 文件分组
//@分组{  文件

//@别名   文件_取文件版本A ()
bool X_File_GetFileVersionA (CXTextA szModuleName, CXTextA& RetStr);



//@分组}  文件
// TODO: 数组操作
//@分组{  数组操作


//@返回   返回文本在数组内的位置,-1为不存在
//@别名   数组_寻找成员_文本(文本数组,被搜寻文本)
int X_Array_FindArrayMembers (CXVector<string> arr,const char *str);



//@分组}  数组操作
// TODO: 线程操作
//@分组{  线程操作

//@别名   线程许可证
#define CRITICALSECTION CRITICAL_SECTION

//@别名   线程_创建线程(传入的子程序,传入的参数,线程ID)
HANDLE X_Thread_CreateThread (LPVOID lpStartAddress,int lpParameter,int& lpThreadId);

//@别名   线程_关闭句柄(线程句柄)
bool X_Thread_CloseHandle(HANDLE handle);

//@别名   线程_打开(线程ID)
bool X_Thread_OpenThread(int ThreadId);

//@备注   GetCurrentThreadId,获取当前线程一个唯一的线程标识符
//@别名   线程_取自线程ID()
int X_Thread_GetCurrentThreadId();

//@备注   GetCurrentThread,获取当前线程的一个伪句柄
//@别名   线程_取自线程句柄()
HANDLE X_Thread_GetCurrentThread();

//@备注   有时执行线程的时候，会自动关闭，此时，可以在多线程的程序里创建COM对象前先初始化，一个线程只能调用一次
//@别名   线程_初始化COM库()
void X_Thread_COMINIT();

//@备注   取消COM库的初始化，如果你在线程头部加入了 线程_初始化COM库 请在尾部加入此命令
//@别名   线程_取消COM库()
void X_Thread_COMUNINIT();

//@备注   成功返回指定窗口的线程ID
//@别名   线程_取ID()
int X_Thread_GetID(HWND hwnd);

//@备注   强制终止正在运行的线程,成功返回真,失败返回假.
//@别名   线程_销毁()
bool X_Thread_Destroy (HANDLE handle);

//@备注   创建并返回一个进入许可证数值，此许可证值用作进入程序中的指定许可代码区，以避免多线程冲突
//@别名   线程_创建进入许可证()
CRITICALSECTION X_Thread_CriticalSection ();

//@备注   删除由"创建进入许可证"命令所创建返回的进入许可证(该命令会在本类被销毁时自动被调用)
//@别名   线程_删除许可证()
void X_Thread_DelSection (CRITICALSECTION &SECTION);

//@备注   根据已经创建的许可证进入指定许可代码区，在此线程未退出之前，其它线程如要通过同一个进入许可证进入该许可代码区则必须先等待此线程退出许可代码区，从而保证了指定许可代码区在任何时候都只能有一条线程进入并执行
//@别名   线程_进入许可区()
void X_Thread_EnterCriticalSection(CRITICALSECTION &SECTION);

//@备注   指示当前线程将退出许可代码区，并允许其它使用同一进入许可证的线程进入此许可代码区
//@别名   线程_退出许可区()
void X_Thread_LeaveCriticalSection(CRITICALSECTION &SECTION);


//@分组}  线程操作
// TODO: 窗口句柄
//@分组{  窗口句柄


//@备注   InvalidateRect
//@别名   窗口_重画(窗口句柄,擦除背景)
bool X_Form_Repaint(HWND hWnd,bool EraseBg);

//@备注   顶级窗口,会在任务条里显示一个按钮.通过本功能可以将其隐藏
//@别名   窗口_隐藏任务按钮(窗口句柄)
void X_Form_HideTaskButton(HWND hWnd);

//@别名   窗口_是否响应(窗口句柄)
bool X_Form_IfNormal(HWND hWnd);

//@别名   窗口_取光标坐标()
bool X_Form_GetCaretPos(POINT& Pos);

//@别名   窗口_取桌面句柄A()
HWND X_Form_GetDesktopHWndA();

//@别名   窗口_取桌面句柄W()
HWND X_Form_GetDesktopHWndW();

//@别名   窗口_嵌入桌面(窗口句柄)
HWND X_Form_EmbedOnDesktop (HWND hWnd);

//@备注   指定一个窗口的新父(返回  前一个父窗口的句柄)
//@别名   窗口_置父(子窗口句柄,父窗口句柄)
HWND X_Form_SetParent(HWND hWndChild,HWND hWndParent);

//@参数   欲设置的窗口句柄
//@参数   窗口新的左边位置,留空或者为NULL/0则不变
//@参数   窗口新的顶边位置,留空或者为NULL/0则不变
//@参数   窗口的新宽度,留空或者为NULL/0则不变
//@参数   窗口的新高度,留空或者为NULL/0则不变
//@别名   窗口_置位置和大小(窗口句柄,左边位置,顶边位置,新宽度,新高度)
bool X_Form_SetPosAndSize(HWND hWnd,int Left=0,int Top=0,int NewWidth=0,int NewHigh=0);


//@分组}  窗口句柄
//@分组{  环境系统

//@别名   系统_是否64位()
bool X_System_SysIs64();

//@备注   仅对编译环境有效    对应 常量_系统类型_\X_OS_
//@别名   系统_取系统类型()
int X_System_WIsOs ();

//@备注   暂时转让控制权，以便让 Windows 操作系统有机会处理其它的如用户键盘或鼠标输入等事件。直到操作系统处理并发送完程序队列中的所有事件后，命令才会返回
//@别名   系统_处理事件()
void X_System_DoEvents();

//@参数   欲执行的cmd命令行
//@参数   回显的函数指针 函数原型(bool func(const char* str) 返回True中断 返回False继续) 可空
//@别名   系统_取DOS执行结果A (cmd命令行,回调指针)
CXTextA X_System_RunCmdA (CXTextA cmd,void*func = nullptr);

//@别名   注册表键类型
struct StructRegKeyA {
    //@别名   键名
    CXTextA Key;
    //@别名   值
    CXTextA Value;
    //@别名   类型
    int Type;
};

//@别名   注册表操作类
class X_System_Class_Reg {
private:
    //@别名   打开项A()
    HKEY OpenA(const char* Path,bool Create=false);

public:

    //@参数   项名称
    //@参数   获取的子项数组
    //@别名   枚举子项A(项名称,子项列表)
    int GetItemListA(const char* name,CXVector<CXTextA> &ItemList);

    //@参数   项名称
    //@参数   获取的返回数据数组
    //@别名   枚举键名A(项名称,返回列表)
    int GetKeyListA(const char* name,CXVector<StructRegKeyA> &List);

    //@备注   对应常量 常量_注册表键类型_/X_REG_
    //@参数   项名称
    //@参数   留空将取第一个
    //@别名   取键名类型A(项名称,键名)
    int GetKeyTypeA(const char* name,const char* KeyName="");

    //@备注   判断指定注册项名称(键名)是否存在存在返回真,否则返回假
    //@参数   欲判断的项名称
    //@参数   欲判断的键名.如果为空则只判断项名称是否存在
    //@返回   存在返回真,否则返回假
    //@别名   是否存在A (项名称,键名)
    bool IfExist (const char* name,const char* KeyName);

    //@备注   将对项和它的子项作出的改动实际写入磁盘
    //@别名   刷新项A (项名称)
    bool ReProject(const char* name);

    //@参数   项名称
    //@参数   键名
    //@参数   欲写入的字节集
    //@参数   写入的类型   对应 常量_注册表键类型_/X_REG_   可空
    //@别名   写入字节集A(项名称,键名,写入字节集,类型)
    bool WriteByteA(const char* name,const char* KeyName,CXBytes WriteByte,int Tyte=0);

    //@参数   项名称
    //@参数   键名
    //@参数   取出数据的类型
    //@别名   取字节集A(项名称,键名,写入字节集,类型)
    CXBytes GetBytesA(const char* name,const char* KeyName,int& Type);

    //@别名   写自定义数据A(项名称,键名,写入字节集,类型)
    bool WriteCustomA(const char* name,const char* KeyName,int Type);

    //@别名   写DWORD值A(项名称,键名,值)
    bool WriteDWORDA(const char* name,const char* KeyName,int num);

    //@别名   取DWORD值A(项名称,键名)
    int GetDWORDA(const char* name,const char* KeyNam);

    //@别名   写二进制值A(项名称,键名,值)
    bool WriteBINA(const char* name,const char* KeyName,int num);

    //@别名   取二进制值A(项名称,键名)
    int GetBINA (const char* name,const char* KeyNam);

    //@别名   写文本值A(项名称,键名,内容)
    bool WriteStringA (const char* name,const char* KeyNam,CXTextA Str);

    //@别名   取文本值A(项名称,键名)
    CXTextA GetStringA (const char* name,const char* KeyNam);

    //@别名   删除键A(项名称,键名)
    bool DelKeyA(const char* name,const char* KeyName);

};


//@分组}  环境系统
// TODO: 网页分组
//@分组{  网页

//@别名   网页_取端口A(网站Url)
int X_Network_GetPortA (const char*Url);

//@别名   网页_取域名A(网站,删除二级域名,保留端口,后缀数量)
CXTextA X_Network_GetDomanNameA (const char*Url,bool DellChild=false,bool ReservedPort=true,int SuffixNum=-1);


//@隐藏{  考虑到openssl的问题,所以将访问功能删除
//@参数   网页地址 需要带上http://或https://
//@参数   提交类型 0:Get 1:POST
//@参数   提交数据 POST有效
//@参数   -1:网址错误 其他:网页状态码
//@返回   返回的数据
//@别名   网页_访问A(网址,访问类型,提交数据,返回状态码)
//CXTextA X_Network_AccessA (const char* Url,int Type=0,const char*SubmitData="",int rCode=0,const char*Head="Accept: */*\nUser-Agent: Mozilla/4.0 (compatible; MSIE 9.0; Windows NT 6.1)\nContent-Type: application/x-www-form-urlencoded",const char*cookies="");
//@隐藏}


//@备注   取出协议头中的某个值
//@别名   网页_协议头取值A(原始头,键名)
CXTextA X_Network_GetHeadsValueA(const char*Head,const char*Key);

//@别名   网页_取单条协议头名A(协议头)
CXTextA X_Network_GetHeadNameA(const char*Head);

//@别名   网页_取单条协议头值A(协议头)
CXTextA X_Network_GetHeadValueA(const char*Head);



//@分组}  网页
// TODO: 程序分组
//@分组{  程序


//@别名   程序_延时(延时时间)
void X_Program_Sleep(int time);

//@备注   仅对编译环境有效
//@别名   程序_是否64位()
bool X_Program_If64();

//@别名   程序_生成GUIDA ()
CXTextA X_Program_CreateGUID (bool mark=false);

//@分组}  程序
// TODO: 常量分组
//@分组{  常量

//@别名   常量_系统类型_未知
#define X_OS_NULL 0
//@别名   常量_系统类型_Windows
#define X_OS_WINDOWS 1
//@别*名   常量_系统类型_Windows64
//#*define ML_OS_WINDOWS64 2
//@别名   常量_系统类型_Linux
#define X_OS_LINUX 3
//@别名   常量_系统类型_MacOS
#define X_OS_MACOS 4
//@别名   常量_系统类型_Android
#define X_OS_ANDROID 5
//@别名   常量_系统类型_Cygwin
#define X_OS_CYGWIN 6
//@别名   常量_系统类型_SunOs
#define X_OS_SUNOS 7
//@别名   常量_系统类型_FreeBSD
#define X_OS_FREEBSD 8
//@别名   常量_系统类型_OpenBSD
#define X_OS_OPENBSD 9
//@别名   常量_系统类型_Aix
#define X_OS_AIX 10

//@别名   常量_注册表键类型_键不存在
#define X_REG_NULL -1
//@别名   常量_注册表键类型_字节集
#define X_REG_NONE 0
//@别名   常量_注册表键类型_字符串值
#define X_REG_SZ 1
//@别名   常量_注册表键类型_可扩充字符串值
#define X_REG_REG_EXPAND_SZ 2
//@别名   常量_注册表键类型_二进制
#define X_REG_BINARY 3
//@别名   常量_注册表键类型_DWORD
#define X_REG_DWORD 4
//@别名   常量_注册表键类型_多字符串值
#define X_REG_MULTI_SZ 7


//@分组}  常量


#endif //XL_XExpand_H
